import type {
  TDate,
  IDateRule,
  TToastIcon,
  TToastPosition,
  TVoidFn,
  TStrOrNum,
  TSwitchType,
  TChooseFileCount,
  TChooseFileSourceType,
  TChooseFileSizeType,
  AnyObject,
  ILoading,
  IGetList,
  IPayType,
  ILocation
} from '@/common/types'
import useUserStore from '@/store/user'

// 格式化时间
export function dateFormat(date:TDate = new Date(), fmt:string = 'YYYY-MM-DD'):string {
  if (typeof date === 'string') date = date.replace(/-/g, '/')
  const time:Date = new Date(date)
  const weekArr:string[] = ['日', '一', '二', '三', '四', '五', '六']
  const o:IDateRule = {
    'M+': time.getMonth() + 1, // 月份
    'D+': time.getDate(), // 日
    'h+': time.getHours(), // 小时
    'm+': time.getMinutes(), // 分
    's+': time.getSeconds(), // 秒
    'q+': Math.floor((time.getMonth() + 3) / 3), // 季度
    S: time.getMilliseconds(), // 毫秒
    W: time.getDay() // 星期
  }
  if (/(Y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, String(time.getFullYear()).substr(4 - RegExp.$1.length))
  }
  for (const k in o) {
    // @ts-ignore
    const val = o[k]
    if (new RegExp('(' + k + ')').test(fmt)) {
      fmt = fmt.replace(
        RegExp.$1,
        RegExp.$1 === 'W'
          ? weekArr[val]
          : RegExp.$1.length === 1
            ? val
            : ('00' + val).substr(String(val).length)
      )
    }
  }
  return fmt
}

// toast弹窗
export function toast(title:string, fn?:TVoidFn, duration:number = 1500, mask:boolean = false, icon:TToastIcon = 'none', position:TToastPosition = 'bottom'):void {
  uni.showToast({
    title,
    icon,
    duration,
    position,
    mask,
    success: (res):void => {
      setTimeout(():void => {
        fn && fn()
      }, duration)
    }
  })
}

// loading弹窗
export function loading(title:string = '加载中...', fn?:TVoidFn, mask:boolean = true):ILoading {
  uni.showLoading({
    title,
    mask,
    success: ():void => {
      fn && fn()
    }
  })
  return {
    hide: ():void => {
      uni.hideLoading()
    }
  }
}

// 权限验证跳转
export function jump(url?:TStrOrNum, type:TSwitchType = 'navigateTo', passport:boolean = true):void {
  // 快捷跳转
  if (url === 'login') {
    jump('/pages/login/index', type, false)
    return
  }
  if (url === 'home') {
    uni.reLaunch({
      url: '/pages/index/index'
    })
    return
  }
  // 是否登录验证
  const userStore = useUserStore()
  if (!userStore.token && passport && typeof url === 'string') {
    jump('login')
    toast('请先登录')
    return
  }
  // 跳转
  if (url && typeof url === 'string') {
    switch (type) {
      case 'navigateTo':
        uni.navigateTo({ url })
        break
      case 'redirectTo':
        uni.redirectTo({ url })
        break
      case 'reLaunch':
        uni.reLaunch({ url })
        break
      case 'switchTab':
        uni.switchTab({ url })
        break
    }
  } else if (url && url as number > 0) {
    uni.navigateBack({ delta: url as number })
  } else {
    const pages = getCurrentPages()
    if (pages.length === 1) jump('home')
    else jump(1)
  }
}

// 获取元素数据
export function getElementInfo(select:string, that?:any):Promise<AnyObject> {
  return new Promise(resolve => {
    let element
    if (select.includes('.')) {
      element = that ? uni.createSelectorQuery().in(that).selectAll(select) : uni.createSelectorQuery().selectAll(select)
    } else {
      element = that ? uni.createSelectorQuery().in(that).select(select) : uni.createSelectorQuery().select(select)
    }
    element.boundingClientRect(res => {
      resolve(res)
    }).exec()
  })
}

// 下载文件
export function downloadFile(url:string):Promise<unknown> {
  return new Promise(resolve => {
    uni.downloadFile({
      url,
      success: (res):void => {
        if (res.statusCode === 200) {
          resolve(res.tempFilePath)
        }
      },
      fail: (err):void => {
        resolve(new Error(err))
      }
    })
  })
}

// 保存文件
export function saveFile(tempFilePath:string):void {
  uni.saveFile({
    tempFilePath,
    success(res) {
      toast('下载成功，文件保存在' + res.savedFilePath)
    }
  })
}

// 查看图片
export function viewImage(current:number, urls:Array<string>, showmenu:boolean = true):void {
  uni.previewImage({
    current,
    urls,
    showmenu
  })
}

// 复制数据
export function copyData<T extends object>(data:T):T {
  return data ? JSON.parse(JSON.stringify(data)) : null
}

// 获取rpx转px值 默认底部悬浮按钮高度
export function px(num:number = 134):number {
  return uni.upx2px(num)
}

// 拨打电话
export function callPhone(phoneNumber:string):void {
  uni.makePhoneCall({
    phoneNumber
  })
}

// 获取列表
export class GetList<T extends AnyObject, K> implements IGetList<T, K> {
  public _has_more:boolean = true
  public total:number = 0

  // eslint-disable-next-line no-useless-constructor
  constructor(
      public api: any,
      public params: T = {} as T,
      public initData?: (data: K) => AnyObject[],
      public page_size: number = 10,
      public page: number = 1
  ) {

  }

  async getList(): Promise<AnyObject[]> {
    let load
    if (!this.params.noLoading) load = loading()

    const res = await this.api(Object.assign({
      pageIndex: this.page,
      pageSize: this.page_size
    }, this.params))
    uni.stopPullDownRefresh()
    load && load.hide()
    const data = res.data || []
    const list: AnyObject[] = (this.initData && this.initData(data)) ?? data
    if (list.length < this.page_size) this._has_more = false
    return list
  }

  async nextPage(): Promise<AnyObject[]> {
    if (this._has_more) {
      this.page++
      return await this.getList()
    }
    return []
  }

  async reload(): Promise<AnyObject[]> {
    this.page = 1
    this._has_more = true
    return await this.getList()
  }

  async clear(): Promise<AnyObject[]> {
    return this.reload()
  }
}

/**
 *  选择文件
 *  count: 最多可以选择的文件个数
 *  sizeType: 是否压缩所选文件 ['original', 'compressed']
 *  sourceType: 图片和视频选择的来源 ['album', 'camera'] ['从相册选择','使用相机拍摄]
 * */
export function chooseFile(count:TChooseFileCount, sourceType?:TChooseFileSourceType, sizeType?:TChooseFileSizeType):Promise<AnyObject[]> {
  return new Promise(resolve => {
    uni.chooseImage({
      count,
      sourceType,
      sizeType,
      complete: (res:AnyObject):void => {
        const msg:string = res.errMsg
        console.log(res)
        if (msg.includes('chooseImage:ok')) {
          resolve(res.tempFiles)
        } else if (msg.includes('cancel')) {
          toast('已取消文件选择')
        } else {
          toast('文件选择失败')
        }
      }
    })
  })
}

// 防抖
export function debounce(fn:()=>void, interval:number = 1000) {
  let timer: number | null
  return () => {
    if (timer) {
      clearTimeout(timer)
      timer = null
    }
    timer = setTimeout(() => {
      fn && fn()
    }, interval)
  }
}

// 从剪贴板获取
export function getClipboard():Promise<AnyObject> {
  return new Promise(resolve => {
    uni.getClipboardData({
      complete: res => {
        uni.hideToast()
        resolve(res)
      }
    })
  })
}

// 复制到剪贴板
export function setClipboard(data:string, showToast = true):Promise<unknown> {
  return new Promise(resolve => {
    uni.setClipboardData({
      data,
      showToast,
      complete: (res):void => {
        if (!showToast) uni.hideToast()
        resolve(res)
      }
    })
  })
}

// 获取坐标
export function getLocation():Promise<ILocation> {
  return new Promise(resolve => {
    uni.getLocation({
      type: 'gcj02',
      geocode: true,
      complete: async res => {
        if (res.errMsg.includes('getLocation:fail')) {
          // await checkOpenGPSServiceByAndroid()
          resolve({
            lat: '', lng: ''
          })
        } else if (res.errMsg === 'getLocation:ok') {
          resolve({
            lat: res.latitude,
            lng: res.longitude
          })
        }
      }
    })
  })
}

/** 检查是否打开GPS功能（android）**/
export async function checkOpenGPSServiceByAndroid() {
  const system = uni.getSystemInfoSync() // 获取系统信息
  if (system.platform === 'android') { // 判断平台
    return openGps()
  }
}
/**
 * 定位权限及弹出权限弹框 监听用户点击按钮
 * **/
let locationApplyCount = 0
export const openGps = () => {
  return new Promise(resolve => {
    plus.android.requestPermissions(
      ['android.permission.ACCESS_FINE_LOCATION'],
      function(resultObj) {
        console.log('resultObj---', resultObj)
        let result = 0
        for (let i = 0; i < resultObj.granted.length; i++) {
          const grantedPermission = resultObj.granted[i]
          // console.log(6, '已获取的权限：' + grantedPermission);
          result = 1
        }
        for (let i = 0; i < resultObj.deniedPresent.length; i++) {
          const deniedPresentPermission = resultObj.deniedPresent[i]
          // console.log(5, '拒绝本次申请的权限：' + deniedPresentPermission);
          locationApplyCount += 1
          result = 0
        }
        for (let i = 0; i < resultObj.deniedAlways.length; i++) {
          const deniedAlwaysPermission = resultObj.deniedAlways[i]
          // console.log(4, '永久拒绝申请的权限：' + deniedAlwaysPermission);
          locationApplyCount += 1
          result = -1
        }
        // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
        if (result != 1) {
          // 如果用户第2次拒绝后，跳转到**应用**的权限页面
          if (locationApplyCount > 2) {
            uni.showModal({
              title: '该功能需要使用定位权限',
              content: '请到应用"设置-隐私-位置"信息中开启权限',
              success(res) {
                if (res.confirm) {
                  const Intent = plus.android.importClass('android.content.Intent')
                  const Settings = plus.android.importClass('android.provider.Settings')
                  const Uri = plus.android.importClass('android.net.Uri')
                  const mainActivity = plus.android.runtimeMainActivity()
                  const intent = new Intent()
                  intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                  const uri = Uri.fromParts('package', mainActivity.getPackageName(), null)
                  intent.setData(uri)
                  mainActivity.startActivity(intent)
                } else if (res.cancel) {
                  toast('请到应用"设置-隐私-位置"信息中开启权限')
                }
                resolve('success')
              }
            })
          } else {
            toast('请到应用"设置-隐私-位置"信息中开启权限')
            resolve('success')
          }
        } else {
          resolve('success')
        }
      }
    )
  })
}

// 支付
export async function pay(orderInfo:any, methods:IPayType, context:any) {
  return new Promise(resolve => {
    /* #ifdef H5*/
    const proxy = context?.proxy
    Object.assign(orderInfo, {
      success: (res:any) => {
        resolve(res)
        console.log(res, 'success')
      },
      cancel: (e) => {
        toast('取消支付')
        console.log(e, 'cancel')
      },
      fail: (e) => {
        toast('支付失败')
        console.log(e, 'fail')
      }
    })
    console.log(orderInfo, '传参')
    proxy?.$wx.chooseWXPay(orderInfo)
    /* #endif*/

    /*
    * App端，支付宝支付 orderInfo 为 String 类型。
    * App端，微信支付 orderInfo 为 Object 类型。
    * */
    /* #ifdef APP-PLUS*/
    uni.requestPayment({
      provider: methods === 'WXPAY' ? 'wxpay' : 'alipay',
      orderInfo,
      complete: (res) => {
        if (res.errMsg === 'requestPayment:ok') resolve(res)
        else toast('取消支付')
      }
    })
    /* #endif*/
  })
}
